#include "db/db.h"
#include "logger.h"

#include <pthread.h>

static pthread_mutex_t mysql_mutex = PTHREAD_MUTEX_INITIALIZER;
static ServerConfig_t mysql_config;

MYSQL *initDB(const ServerConfig_t *config)
{
    MYSQL *conn = mysql_init(NULL);

    if (conn == NULL)
    {
        PRINT_ERROR("initDB failed");
        LOG_ERROR("MYSQL", "initDB failed");
        exit(EXIT_FAILURE);
    }

    unsigned int timeout = 5; // 设置超时时间
    mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
    if (mysql_real_connect(conn, config->mysql_host, config->mysql_user,
                           config->mysql_password, config->mysql_db,
                           config->mysql_port, NULL, 0) == NULL)
    {
        exitError(conn);
    }
    else
    {
        PRINT_INFO("Connected to mysql %s:%s", config->mysql_host, config->mysql_db);
        LOG_INFO("MYSQL", "Connected to mysql %s:%s", config->mysql_host, config->mysql_db);
    }

    memcpy(&mysql_config, config, sizeof(ServerConfig_t));

    return conn;
}

MYSQL *threadConnectDB()
{
    pthread_mutex_lock(&mysql_mutex);

    MYSQL *conn = mysql_init(NULL);

    if (conn == NULL)
    {
        PRINT_ERROR("thread failed to init mysql");
        LOG_ERROR("MYSQL", "thread failed to init mysql");
        pthread_mutex_unlock(&mysql_mutex);
        exit(EXIT_FAILURE);
    }

    unsigned int timeout = 5; // 设置超时时间
    mysql_options(conn, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
    if (mysql_real_connect(conn, mysql_config.mysql_host, mysql_config.mysql_user,
                           mysql_config.mysql_password, mysql_config.mysql_db,
                           mysql_config.mysql_port, NULL, 0) == NULL)
    {
        pthread_mutex_unlock(&mysql_mutex);
        exitError(conn);
    }
    else
    {
        PRINT_INFO("Thread connected to mysql %s:%s", mysql_config.mysql_host, mysql_config.mysql_db);
        LOG_INFO("MYSQL", "Thread connected to mysql %s:%s", mysql_config.mysql_host, mysql_config.mysql_db);
    }

    pthread_mutex_unlock(&mysql_mutex);
    return conn;
}

void closeDB(MYSQL *conn)
{
    mysql_close(conn);
}

void exitError(MYSQL *conn)
{
    PRINT_ERROR(mysql_error(conn));
    LOG_ERROR("MYSQL", "%s", mysql_error(conn));
    mysql_close(conn);
    exit(EXIT_FAILURE);
}

void selectUsers(MYSQL *conn)
{
    if (mysql_query(conn, "SELECT user_id, username, created_time FROM users"))
    {
        exitError(conn);
    }

    MYSQL_RES *result = mysql_store_result(conn);
    if (result == NULL)
    {
        exitError(conn);
    }

    int num_fields = mysql_num_fields(result);
    MYSQL_ROW row;
    MYSQL_FIELD *fields = mysql_fetch_fields(result);

    for (int i = 0; i < num_fields; i++)
    {
        printf("%s ", fields[i].name);
    }
    printf("\n");

    while ((row = mysql_fetch_row(result)))
    {
        for (int i = 0; i < num_fields; i++)
        {
            printf("%s ", row[i] ? row[i] : "NULL");
        }
        printf("\n");
    }

    mysql_free_result(result);
}

MYSQL_RES *excutesql(const char *sel, MYSQL *conn)
{
    MYSQL_RES *result;
    if (mysql_query(conn, sel))
    {
        exitError(conn);
        return NULL;
    }
    result = mysql_store_result(conn);
    return result;
}
